//
// Created by zhulingfeng on 2020/2/6.
//

#include <gtest/gtest.h>
#include <binary_tree/create_binary_tree.hpp>
#include "binary_tree/binary_tree_traversal.hpp"
#include "create_binary_tree_test.hpp"

TEST_F(CreateBinaryTreeTest, TestCreateBTFromLevelOrder) {
  std::vector<int> output;
  for (int i = 0; i < level_order_strings_.size(); ++i) {
    output.clear();
    auto root = CreateBTFromLevelOrder(level_order_strings_[i]);
    LevelOrderTraversalIterative(root, output);
    EXPECT_EQ(level_order_gts_[i], output);
  }
  // Exception test.
  for (const auto &i : level_order_strings_exception_data_) {
    ASSERT_THROW(CreateBTFromLevelOrder(i), std::invalid_argument);
  }
}

TEST_F(CreateBinaryTreeTest, TestCreateBTFromPreOrder) {
  std::vector<int> output;
  for (int i = 0; i < pre_order_strings_.size(); ++i) {
    output.clear();
    auto root = CreateBTFromPreOrder(pre_order_strings_[i]);
    PreOrderTraversalRecursive(root, output);
    EXPECT_EQ(pre_order_gts_[i], output);
  }
}

TEST_F(CreateBinaryTreeTest, TestCreateBTFromPostOrder) {
  std::vector<int> output;
  for (int i = 0; i < post_order_strings_.size(); ++i) {
    output.clear();
    auto root = CreateBTFromPostOrder(post_order_strings_[i]);
    PostOrderTraversalRecursive(root, output);
    EXPECT_EQ(post_order_gts_[i], output);
  }
}

void GetPostFromPreAndInOrderIndirectly(std::vector<int> &pre,
                                        std::vector<int> &in,
                                        std::vector<int> &output) {
  auto root = CreateBTFromPreAndInOrder(pre, in);
  PostOrderTraversalRecursive(root, output);
}

TEST_F(CreateBinaryTreeTest, TestCreateBTFromPreAndInOrder) {
  std::vector<int> pre, in, post, output;
  // Functional test.
  for (int i = 0; i < pre_order_gts_.size(); i++) {
    pre = pre_order_gts_[i];
    in = in_order_gts_[i];
    post = post_order_gts_[i];
    output.clear();
    GetPostFromPreAndInOrderIndirectly(pre, in, output);
    EXPECT_EQ(post, output);
  }
  // Exception test.
  for (int i = 0; i < pre_order_exception_data_.size(); i++) {
    pre = pre_order_exception_data_[i];
    in = in_order_exception_data_[i];
    ASSERT_THROW(CreateBTFromPreAndInOrder(pre, in), std::invalid_argument);
  }
}

TEST_F(CreateBinaryTreeTest, TestGetPostFromPreAndInOrder) {
  std::vector<int> pre, in, post, output;
  // Functional test.
  for (int i = 0; i < pre_order_gts_.size(); i++) {
    pre = pre_order_gts_[i];
    in = in_order_gts_[i];
    post = post_order_gts_[i];
    output.clear();
    GetPostFromPreAndInOrder(pre, in, output);
    EXPECT_EQ(post, output);
    output = GetPostFromPreAndInOrder(pre, in);
    EXPECT_EQ(post, output);
  }
  // Exception test.
  for (int i = 0; i < pre_order_exception_data_.size(); i++) {
    pre = pre_order_exception_data_[i];
    in = in_order_exception_data_[i];
    ASSERT_THROW(GetPostFromPreAndInOrder(pre, in), std::invalid_argument);
  }
}
